package cn.taketoday.live.service.impl;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Base64;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import cn.taketoday.live.component.ServerAddressComponent;
import cn.taketoday.live.component.TaskRegisterComponent;
import cn.taketoday.live.component.ThreadComponent;
import cn.taketoday.live.config.CenterSetConfig;
import cn.taketoday.live.config.GlobalData;
import cn.taketoday.live.config.settings.AdvertSetConf;
import cn.taketoday.live.config.settings.AutoReplySetConf;
import cn.taketoday.live.config.settings.ClockInSetConf;
import cn.taketoday.live.config.settings.ThankFollowSetConf;
import cn.taketoday.live.config.settings.ThankGiftSetConf;
import cn.taketoday.live.config.settings.ThankWelcomeSetConf;
import cn.taketoday.live.data.enums.ShieldMessage;
import cn.taketoday.live.data.user.UserCookie;
import cn.taketoday.live.data.user.UserMedal;
import cn.taketoday.live.file.ProFileTools;
import cn.taketoday.live.handler.MessageHandler;
import cn.taketoday.live.http.BilibiliHttpRequests;
import cn.taketoday.live.http.HttpOtherData;
import cn.taketoday.live.service.ClientService;
import cn.taketoday.live.service.SettingsService;
import cn.taketoday.live.tools.CurrencyTools;
import cn.taketoday.live.tools.ParseSetStatusTools;
import cn.taketoday.live.utils.ObjectUtils;
import cn.taketoday.live.utils.SchedulingRunnableUtil;

/**
 * @author BanqiJane
 * @ClassName SetServiceImpl
 * @Description TODO
 * @date 2020年8月10日 下午12:17:03
 * @Copyright:2020 blogs.acproject.xyz Inc. All rights reserved.
 */
@SuppressWarnings("all")
@Service
public class SetServiceImpl implements SettingsService {
  private Logger LOGGER = LogManager.getLogger(SetServiceImpl.class);
  private final String cookies = "ySZL4SBB";
  private ClientService clientService;
  private ThreadComponent threadComponent;
  private ServerAddressComponent serverAddressComponent;
  private TaskRegisterComponent taskRegisterComponent;

  public void init(int i) {
    Hashtable<String, String> hashtable = new Hashtable<String, String>();
    String cookieString = null;
    final Base64.Decoder decoder = Base64.getDecoder();
    try {
      hashtable.putAll(ProFileTools.read("DanmujiProfile"));
    }
    catch (Exception e) {
      // TODO: handle exception
    }
    // 读取本地cookie
    try {
      cookieString = !StringUtils.isEmpty(hashtable.get(cookies))
                     ? new String(decoder.decode(hashtable.get(cookies)))
                     : null;
    }
    catch (Exception e) {
      // TODO 自动生成的 catch 块
      LOGGER.error("获取本地cookie失败,请重新登录" + e);
      cookieString = null;
    }
    if (!StringUtils.isEmpty(cookieString)) {
      if (StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        GlobalData.USERCOOKIE = cookieString;
      }
    }
    BilibiliHttpRequests.getUserInfo();
    if (GlobalData.USER == null) {
      GlobalData.USERCOOKIE = null;
    }
    else {
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        hashtable.put(cookies, Base64.getEncoder().encodeToString(GlobalData.USERCOOKIE.getBytes()));
      }
    }
    // 读取本地set
    final String set = hashtable.get("set");
    try {
      GlobalData.centerSetConf = !StringUtils.isEmpty(set)
                                     ? ObjectUtils.fromJSON(new String(decoder.decode(set)), CenterSetConfig.class)
                                     : null;
    }
    catch (Exception e) {
      // TODO: handle exception
      LOGGER.error("读取配置文件失败,尝试重新读取" + e);
      GlobalData.centerSetConf = null;
    }
    //初始化配置文件开始
    if (GlobalData.centerSetConf == null) {
      GlobalData.centerSetConf = new CenterSetConfig(new ThankGiftSetConf(), new AdvertSetConf(),
                                                     new ThankFollowSetConf(), new AutoReplySetConf(), new ClockInSetConf(),
                                                     new ThankWelcomeSetConf());
    }
    else {
      if (GlobalData.centerSetConf.getRoomid() != null && GlobalData.centerSetConf.getRoomid() > 0)
        GlobalData.ROOMID_SAFE = GlobalData.centerSetConf.getRoomid();
      if (GlobalData.ROOMID_SAFE != null && GlobalData.ROOMID_SAFE > 0)
        GlobalData.centerSetConf.setRoomid(GlobalData.ROOMID_SAFE);
    }
    if (GlobalData.centerSetConf.getAdvert() == null) {
      GlobalData.centerSetConf.setAdvert(new AdvertSetConf());
    }
    if (GlobalData.centerSetConf.getFollow() == null) {
      GlobalData.centerSetConf.setFollow(new ThankFollowSetConf());
    }
    if (GlobalData.centerSetConf.getThank_gift() == null) {
      GlobalData.centerSetConf.setThank_gift(new ThankGiftSetConf());
    }
    if (GlobalData.centerSetConf.getReply() == null) {
      GlobalData.centerSetConf.setReply(new AutoReplySetConf());
    }
    if (GlobalData.centerSetConf.getClock_in() == null) {
      GlobalData.centerSetConf.setClock_in(new ClockInSetConf(false, "签到"));
    }
    if (GlobalData.centerSetConf.getWelcome() == null) {
      GlobalData.centerSetConf.setWelcome(new ThankWelcomeSetConf());
    }
    //初始化配置文件结束
    hashtable.put("set", Base64.getEncoder().encodeToString(GlobalData.centerSetConf.toJson().getBytes()));
    ProFileTools.write(hashtable, "DanmujiProfile");
    try {
      GlobalData.centerSetConf = ObjectUtils.fromJSON(new String(decoder.decode(set)), CenterSetConfig.class);
      LOGGER.debug("读取配置文件成功");
    }
    catch (Exception e) {
      // TODO: handle exception
      LOGGER.error("读取配置文件失败" + e);
    }
    // 分离cookie
    if (!StringUtils.isEmpty(GlobalData.USERCOOKIE) && GlobalData.COOKIE == null) {
      String key = null;
      String value = null;
      int controlNum = 0;
      String cookie = GlobalData.USERCOOKIE;
      GlobalData.COOKIE = new UserCookie();
      cookie = cookie.trim();
      String[] a = cookie.split(";");
      for (String string : a) {
        if (string.contains("=")) {
          key = string.split("=")[0];
          value = string.split("=")[1];
          if (key.equals("DedeUserID")) {
            GlobalData.COOKIE.setDedeUserID(value);
            controlNum++;
          }
          else if (key.equals("bili_jct")) {
            GlobalData.COOKIE.setBili_jct(value);
            controlNum++;
          }
          else if (key.equals("DedeUserID__ckMd5")) {
            GlobalData.COOKIE.setDedeUserID__ckMd5(value);
            controlNum++;
          }
          else if (key.equals("sid")) {
            GlobalData.COOKIE.setSid(value);
            controlNum++;
          }
          else if (key.equals("SESSDATA")) {
            GlobalData.COOKIE.setSESSDATA(value);
            controlNum++;
          }
          else {
//						LOGGER.debug("获取cookie失败，字段为" + key);
          }
        }
      }
      if (controlNum == 5) {
        LOGGER.debug("用户cookie装载成功");
        controlNum = 0;
      }
      else {
        LOGGER.debug("用户cookie装载失败");
        GlobalData.COOKIE = null;
      }
      updateSettings(GlobalData.centerSetConf);
    }
    if (i == 0) {
      // 公告和检查更新
      System.out.println(
              "参考本地浏览器进入设置页面地址: 1、http://127.0.0.1:" + serverAddressComponent.getPort() + ";2、http://localhost:"
                      + serverAddressComponent.getPort() + ";3、" + serverAddressComponent.getAddress());
      System.out.println();

      // 自动连接
      if (GlobalData.centerSetConf.isIs_auto() && GlobalData.centerSetConf.getRoomid() > 0) {
        try {
          clientService.startConnService(GlobalData.centerSetConf.getRoomid());
        }
        catch (Exception e) {
          e.printStackTrace();
        }
      }

      // window用默认浏览器打开网页
//      try {
//        Runtime.getRuntime()
//                .exec("rundll32 url.dll,FileProtocolHandler " + serverAddressComponent.getAddress());
//      }
//      catch (IOException e) {
//        // TODO Auto-generated catch block
//        System.out.println(
//                "自动打开浏览器错误:当前系统缺少rundll32 url.dll组件或者不是window系统，无法自动启动默认浏览器打开配置页面，请手动打开浏览器地址栏输入http://127.0.0.1:23333进行配置");
//      }
    }
    hashtable.clear();
  }

  // 保存配置文件
  public void update(CenterSetConfig centerSetConf) {
    if (centerSetConf.toJson().equals(GlobalData.centerSetConf.toJson())) {
      LOGGER.debug("保存配置文件成功");
      return;
    }
    if (GlobalData.ROOMID_SAFE != null && GlobalData.ROOMID_SAFE > 0) {
      centerSetConf.setRoomid(GlobalData.ROOMID_SAFE);
    }
    Hashtable<String, String> hashtable = new Hashtable<>();

    final Base64.Encoder encoder = Base64.getEncoder();
    if (GlobalData.USER != null) {
      hashtable.put(cookies, encoder.encodeToString(GlobalData.USERCOOKIE.getBytes()));
    }

    hashtable.put("set", encoder.encodeToString(centerSetConf.toJson().getBytes()));
    ProFileTools.write(hashtable, "DanmujiProfile");
    try {
      final Map<String, String> danmujiProfile = ProFileTools.read("DanmujiProfile");
      final String set = danmujiProfile.get("set");

      GlobalData.centerSetConf = CenterSetConfig.fromBase64String(set);
      updateSettings(centerSetConf);
      LOGGER.debug("保存配置文件成功");
    }
    catch (Exception e) {
      // TODO: handle exception
      LOGGER.error("保存配置文件失败:" + e);
    }
    hashtable.clear();
  }

  public void connectSet(CenterSetConfig centerSetConf) {
    Hashtable<String, String> hashtable = new Hashtable<>();
    final Base64.Encoder encoder = Base64.getEncoder();
    if (GlobalData.USER != null) {
      hashtable.put(cookies, encoder.encodeToString(GlobalData.USERCOOKIE.getBytes()));
    }
    hashtable.put("set", encoder.encodeToString(centerSetConf.toJson().getBytes()));
    ProFileTools.write(hashtable, "DanmujiProfile");
    try {

      final Map<String, String> danmujiProfile = ProFileTools.read("DanmujiProfile");
      GlobalData.centerSetConf = ObjectUtils.fromJSON(Base64.getDecoder().decode(danmujiProfile.get("set")),
                                                      CenterSetConfig.class);
      if (GlobalData.centerSetConf.getAdvert() == null) {
        GlobalData.centerSetConf.setAdvert(new AdvertSetConf());
      }
      if (GlobalData.centerSetConf.getFollow() == null) {
        GlobalData.centerSetConf.setFollow(new ThankFollowSetConf());
      }
      if (GlobalData.centerSetConf.getThank_gift() == null) {
        GlobalData.centerSetConf.setThank_gift(new ThankGiftSetConf());
      }
      if (GlobalData.centerSetConf.getReply() == null) {
        GlobalData.centerSetConf.setReply(new AutoReplySetConf());
      }
      if (GlobalData.centerSetConf.getClock_in() == null) {
        GlobalData.centerSetConf.setClock_in(new ClockInSetConf(false, "签到"));
      }
      if (GlobalData.centerSetConf.getWelcome() == null) {
        GlobalData.centerSetConf.setWelcome(new ThankWelcomeSetConf());
      }
      if (GlobalData.ROOM_ID != null) {
        updateSettings(centerSetConf);
      }
      LOGGER.debug("读取配置文件历史房间成功");
    }
    catch (Exception e) {
      // TODO: handle exception
      LOGGER.error("读取配置文件历史房间失败:" + e);
    }
    hashtable.clear();
  }

  /**
   * 保存配置并执行
   */
  public void updateSettings(CenterSetConfig centerSetConf) {
    SchedulingRunnableUtil task = new SchedulingRunnableUtil("dosignTask", "dosign");
    SchedulingRunnableUtil dakatask = new SchedulingRunnableUtil("dosignTask", "clockin");
    //每日签到
    if (GlobalData.centerSetConf.isIs_dosign()) {
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        if (!GlobalData.is_sign) {
          BilibiliHttpRequests.signIn();
          taskRegisterComponent.addTask(task, "0 30 0 * * ?");
          GlobalData.is_sign = true;
        }
      }
    }
    else {
      try {
        taskRegisterComponent.removeTask(task);
      }
      catch (Exception e) {
        // TODO 自动生成的 catch 块
        LOGGER.error("清理定时任务错误：" + e);
      }
    }
    if (centerSetConf.getClock_in().isIs_open()) {
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        //这里开启一个匿名线程用于打卡
        new Thread(() -> {
          List<UserMedal> userMedals = CurrencyTools.getAllUserMedals();
          int max = CurrencyTools.clockIn(userMedals);
          if (max == userMedals.size()) {
            HttpOtherData.httpPOSTSetClockInRecord();
          }
        }).start();
      }
      taskRegisterComponent.addTask(dakatask, "0 35 0 * * ?");
    }
    else {
      try {
        taskRegisterComponent.removeTask(dakatask);
      }
      catch (Exception e) {
        LOGGER.error("清理定时任务错误：" + e);
      }
    }
    if (GlobalData.ROOM_ID == null || GlobalData.ROOM_ID <= 0) {
      return;
    }
    if (GlobalData.webSocketProxy == null) {
      return;
    }
    if (GlobalData.webSocketProxy != null && !GlobalData.webSocketProxy.isOpen()) return;
    // parsemessagethread start
    final Map<ShieldMessage, Boolean> messageMap = ParseSetStatusTools.getMessageMap(centerSetConf, GlobalData.lIVE_STATUS);
    threadComponent.configureMessageHandler(messageMap, centerSetConf);
    // logthread
    if (centerSetConf.isIs_log()) {
      threadComponent.startLogThread();
    }
    else {
      threadComponent.closeLogThread();
    }
    // need login
    if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
      // advertthread
      if (centerSetConf.getAdvert().isIs_live_open()) {
        if (GlobalData.lIVE_STATUS != 1) {
          threadComponent.closeAdvertThread();
        }
        else {
          if (centerSetConf.getAdvert().isIs_open()) {
            threadComponent.startAdvertThread(centerSetConf);
          }
          else {
            threadComponent.setAdvertThread(centerSetConf);
            threadComponent.closeAdvertThread();
          }
        }
      }
      else {
        if (centerSetConf.getAdvert().isIs_open()) {
          threadComponent.startAdvertThread(centerSetConf);
        }
        else {
          threadComponent.setAdvertThread(centerSetConf);
          threadComponent.closeAdvertThread();
        }
      }
      // autoreplythread
      if (centerSetConf.getReply().isIs_live_open()) {
        if (GlobalData.lIVE_STATUS != 1) {
          threadComponent.closeAutoReplyThread();
        }
        else {
          if (centerSetConf.getReply().isEnable()) {
            threadComponent.startAutoReplyThread(centerSetConf);
          }
          else {
            threadComponent.setAutoReplyThread(centerSetConf);
            threadComponent.closeAutoReplyThread();
          }
        }
      }
      else {
        if (centerSetConf.getReply().isEnable()) {
          threadComponent.startAutoReplyThread(centerSetConf);
        }
        else {
          threadComponent.setAutoReplyThread(centerSetConf);
          threadComponent.closeAutoReplyThread();
        }
      }
      // useronlinethread && smallHeartThread
      if (centerSetConf.isIs_online()) {
        threadComponent.startUserOnlineThread();
        if (centerSetConf.isIs_sh() && GlobalData.lIVE_STATUS == 1) {
          threadComponent.startSmallHeartThread();
        }
        else {
          threadComponent.closeSmallHeartThread();
        }
      }
      else {
        threadComponent.closeSmallHeartThread();
        threadComponent.closeUserOnlineThread();
      }
      // sendbarragethread
      final MessageHandler messageHandler = MessageHandler.getInstance();
      if (GlobalData.advertThread == null
              && !messageHandler.getMessageControlMap().get(ShieldMessage.is_followThank)
              && !messageHandler.getMessageControlMap().get(ShieldMessage.is_welcomeThank)
              && !messageHandler.getMessageControlMap().get(ShieldMessage.is_giftThank)) {
        threadComponent.closeSendBarrageThread();
        GlobalData.thankGiftConcurrentHashMap.clear();
      }
      else {
        threadComponent.startSendBarrageThread();
      }
    }
    else {

      GlobalData.COOKIE = null;
      GlobalData.USER = null;
      GlobalData.USERCOOKIE = null;
      GlobalData.USER_BARRAGE_MESSAGE = null;
      threadComponent.closeAdvertThread();
      threadComponent.closeUserOnlineThread();
      threadComponent.closeGiftShieldThread();
      threadComponent.closeSendBarrageThread();
      threadComponent.closeFollowShieldThread();
      threadComponent.closeWelcomeShieldThread();
      threadComponent.closeSmallHeartThread();
    }
    if (GlobalData.webSocketProxy != null && !GlobalData.webSocketProxy.isOpen()) {
      threadComponent.closeHeartByteThread();
      threadComponent.disableMessageHandler();
      threadComponent.closeUserOnlineThread();
      threadComponent.closeFollowShieldThread();
      threadComponent.closeAdvertThread();
      threadComponent.closeSendBarrageThread();
      threadComponent.closeLogThread();
      threadComponent.closeGiftShieldThread();
      threadComponent.closeAutoReplyThread();
      threadComponent.closeSmallHeartThread();
      threadComponent.closeWelcomeShieldThread();
      GlobalData.SHIELDGIFTNAME = null;
      GlobalData.thankGiftConcurrentHashMap.clear();
      GlobalData.logString.clear();
      GlobalData.IS_SHIELD_FOLLOW = false;
      GlobalData.IS_SHIELD_WELCOME = false;
    }
  }

  public void quit() {
    GlobalData.COOKIE = null;
    GlobalData.USER = null;
    GlobalData.USERCOOKIE = null;
    GlobalData.USER_BARRAGE_MESSAGE = null;
    threadComponent.closeAdvertThread();
    threadComponent.closeUserOnlineThread();
    threadComponent.closeGiftShieldThread();
    threadComponent.closeFollowShieldThread();
    threadComponent.closeAutoReplyThread();
    threadComponent.closeSendBarrageThread();
    threadComponent.closeSmallHeartThread();
    threadComponent.closeWelcomeShieldThread();
    // remove task all shutdown !!!!!!
    try {
      taskRegisterComponent.destroy();
    }
    catch (Exception e) {
      // TODO 自动生成的 catch 块
      LOGGER.error("清理定时任务错误：" + e);
    }
    GlobalData.thankGiftConcurrentHashMap.clear();
    updateSettings(GlobalData.centerSetConf);
    LOGGER.debug("用户退出成功");
  }

  @Autowired
  public void setClientService(ClientService clientService) {
    this.clientService = clientService;
  }

  @Autowired
  public void setThreadComponent(ThreadComponent threadComponent) {
    this.threadComponent = threadComponent;
  }

  @Autowired
  public void setServerAddressComponent(ServerAddressComponent serverAddressComponent) {
    this.serverAddressComponent = serverAddressComponent;
  }

  @Autowired
  public void setTaskRegisterComponent(TaskRegisterComponent taskRegisterComponent) {
    this.taskRegisterComponent = taskRegisterComponent;
  }
}
